package com.shoes.utils;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;

/**
 * AES 256bit 加密
 * 256bit AES加密 需要替换jre/lib/security/local_policy.jar、jre/lib/security/US_export_policy.jar
 * 并导入bcprov_jdk15-133.jar包
 * @author Aci
 *
 */

public class AES {
    public static void main(String[] args) {
        System.out.println(decrypt("TGHbWnFg1zCKQzeMrGZHgETU15sTJDTBdp8GrXgRWZojYVtgqAfV+YHmLuPnwjjvynz3oHy2xTCSz5U95N67Qw=="));
        System.out.println(decrypt("GZg76iO6X/oClZv0d3xupiSZUNzCUKtRD3R5qAi5Se1bauaWbQsmlFfOrvaKJyisKrQcMKVlfXT0CGszlddRdg=="));
    }
    public static final String CIPHER_ALGORITHM = "AES/CBC/PKCS7Padding";
    private static String CHARSET = "UTF-8";
    private static String srcKey = "a!g(201#co'e,e*f";			//16个字符的密钥 AES128bit

    private static byte[] ivbyte = { 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32,
            0x31, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31 };

    /**
     * 设置密钥
     * 		16位ASCII字符
     */
    public static void setSecret(String srcKey) {
        AES.srcKey = srcKey;
    }

    /**
     * 设置BCB模式的向量
     * 		16位
     */
    public static void setIv(byte[] ivbyte) {
        AES.ivbyte = ivbyte;
    }

    public static void setCharset(String charset) throws UnsupportedEncodingException {
        if(!Charset.isSupported(charset)) {
            throw new UnsupportedEncodingException("不支持字符编码:" + charset);
        }
        AES.CHARSET = charset;
    }

    // 加密
    public static String encrypt(String sSrc){
        try {
            Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);// "算法/模式/补码方式"
            IvParameterSpec iv = new IvParameterSpec(ivbyte);// 使用CBC模式，需要一个向量iv，可增加加密算法的强�?
            cipher.init(Cipher.ENCRYPT_MODE, toKey(), iv);
//			cipher.init(Cipher.ENCRYPT_MODE, toKey());
            byte[] encrypted = cipher.doFinal(sSrc.getBytes(CHARSET));
            return Base64Encoder.encode(encrypted);// 此处使用BASE64转成String，不能new String 使用aes加密后的字节再通过base64加密
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    // 解密
    public static String decrypt(String sSrc) {

        try {
            Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            IvParameterSpec iv = new IvParameterSpec(ivbyte);
            cipher.init(Cipher.DECRYPT_MODE, toKey(), iv);
//			cipher.init(Cipher.DECRYPT_MODE, toKey());

            byte[] encrypted1 = Base64Decoder.decodeToBytes(sSrc);// 先用base64解密
            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original, CHARSET);
            return originalString;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private static Key toKey() throws NoSuchAlgorithmException, NoSuchProviderException {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
//		KeyGenerator kgen = KeyGenerator.getInstance("AES");
//		kgen.init(256, new SecureRandom(srcKey.getBytes()));		//以srcKey作为随机源 产生一个密钥(此方法不要求srcKey的长度一定是128位)
//		SecretKey secretKey = kgen.generateKey();
//		byte[] enCodeFormat = secretKey.getEncoded();				//将密钥转为byte数组
        SecretKeySpec skeySpec = new SecretKeySpec(srcKey.getBytes(), "AES");
        return skeySpec;
    }
}
